/**
 * 
 */
package com.goldentrail.dataobject;

import java.util.Enumeration;
import java.util.Hashtable;

import org.json.JSONException;
import org.json.JSONObject;

/**
 * @author dey
 * 
 */
public class Invocation {

	private String invocationId = null;
	private Hashtable<String, DataArtifact> inputData = new Hashtable<String, DataArtifact>();
	private Hashtable<String, DataArtifact> outputData = new Hashtable<String, DataArtifact>();
	private String type = null;
	private String nodeUri = null;

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "Invocation [invocationId=" + invocationId + ", inputData="
				+ inputData + ", outputData=" + outputData + "] \n ";
	}

	/**
	 * 
	 */
	public Invocation() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * @return the invocationId
	 */
	public String getInvocationId() {
		return invocationId;
	}

	/**
	 * @param invocationId
	 *            the invocationId to set
	 */
	public void setInvocationId(String invocationId) {
		this.invocationId = invocationId;
	}

	/**
	 * @return the inputData
	 */
	public Hashtable<String, DataArtifact> getInputData() {
		return inputData;
	}

	/**
	 * @param inputData
	 *            the inputData to set
	 */
	public void setInputData(Hashtable<String, DataArtifact> inputData) {		
		String key;
		Enumeration<String> e = inputData.keys();
    	while (e.hasMoreElements()) {
    		key = e.nextElement();
    		if (!(this.inputData.contains(key))) {
    			this.inputData.put(key, inputData.get(key));
    		}
    	}
	}

	/**
	 * @return the outputData
	 */
	public Hashtable<String, DataArtifact> getOutputData() {
		return outputData;
	}

	/**
	 * @param outputData
	 *            the outputData to set
	 */
	public void setOutputData(Hashtable<String, DataArtifact> outputData) {		
		String key;
		Enumeration<String> e = outputData.keys();
    	while (e.hasMoreElements()) {
    		key = e.nextElement();
    		if (!(this.outputData.contains(key))) {
    			this.outputData.put(key, outputData.get(key));
    		}
    	}
	}

	public String getJSONString() {
		JSONObject json = new JSONObject();
		try {
			json.put("id", getInvocationId());
			json.put("type", "invoc");

		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return json.toString();
	}

	public static Invocation fromJSON(JSONObject json) {
		Invocation invoc = new Invocation();
		try {
			invoc.setInvocationId(json.getString("id"));
			invoc.setType(json.getString("type"));
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return invoc;
	}

	public static Invocation fromJSON(String jsonString) {
		Invocation invoc = new Invocation();
		try {
			JSONObject json = new JSONObject(jsonString);
			invoc.setInvocationId(json.getString("id"));
			invoc.setType(json.getString("type"));
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return invoc;
	}

	/**
	 * @return the type
	 */
	public String getType() {
		return type;
	}

	/**
	 * @param type
	 *            the type to set (should be run or invoc)
	 */
	public void setType(String type) {
		this.type = type;
	}

	/**
	 * @return the nodeUri. For internal use in Neo4j
	 */
	public String getNodeUri() {
		return nodeUri;
	}

	/**
	 * @param nodeUri
	 *            the nodeUri to set. For internal use in Neo4j
	 */
	public void setNodeUri(String nodeUri) {
		this.nodeUri = nodeUri;
	}

	/**
	 * Checks equivalence based on nodeUris if available, else just uses
	 * invocationId - not trustworthy if nodeUri not available, which is only
	 * when the node was returned from the database
	 * 
	 * @param invoc
	 *            the invocation to check equivalence against
	 * @return true if equal, false otherwise
	 */
	public boolean equals(Invocation invoc) {
		if (this.getNodeUri() != null && invoc.getNodeUri() != null) {
			return this.getNodeUri().equals(invoc.getNodeUri());
		} else
			return this.getInvocationId().equals(invoc.getInvocationId());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object o) {
		if (o instanceof Invocation)
			return this.equals((Invocation) o);
		else
			return false;
	}

}
